package anatex.kea.genex.extractor;

import java.text.BreakIterator;
import java.util.*;

import javax.persistence.TypedQuery;

import anatex.domain.*;

import org.apache.commons.collections.iterators.ArrayListIterator;

import anatex.kea.genex.GenEx;

public class Stemmer {
	CustomLocale loc = null;
	Parameters parameters 	= null;
	ArrayList<String> words = null;
	ArrayList<String> stems, stemPhrases = null;
	ArrayList<String> stopWords = null;
	
	public Stemmer(ArrayList<String> w, Parameters p, CustomLocale l) {
		
		loc = l;
		parameters = p;
		words = w;
	}
	
	protected ArrayList<String> getStopWords() {
		if (null == stopWords) {
			stopWords = new ArrayList<String>();
			
			//TODO must get locale from doc
			List<Stopword> s = Stopword.findStopwordsByCustomLocale(loc).getResultList();
			Iterator<Stopword> sit = s.iterator();
			
			while (sit.hasNext()) {
				stopWords.add(sit.next().getWord());
			}
		}
		
		return stopWords;
	}
	
	protected void removeStopwords() {
		stems = (ArrayList<String>)words.clone();
		String word;

		//lowecase stems
		ListIterator<String> it = (ListIterator<String>)stems.listIterator();
		while (it.hasNext()) {
			word = it.next().toLowerCase();
			it.set(word);
		}
		
		//remove stopwords
		ArrayList<String> sw = getStopWords();
		stems.removeAll(sw);
		
		it = (ListIterator<String>)stems.listIterator();
		
		int length = 0;
		int maxLength = (Integer)parameters.get(Parameters.STEM_LENGTH);
		while (it.hasNext()) {
			word = (String)it.next();
			
			if (word.length() < 3) {
				it.remove();
			} else {
				length = word.length() > maxLength ? maxLength : word.length();
				it.set(word.substring(0, length));
			}
		}
	}
	
	protected void stem() {
		//1. Find Single Stems
		stems = new ArrayList<String>();
		removeStopwords();
	}
	
	protected void stemPhrases(String text) {
		//4. Find Stem Phrases
		stemPhrases = new ArrayList<String>();
		int maxLength = (Integer)parameters.get(Parameters.STEM_LENGTH);
		getStopWords();
		
		for (int i = 2; i <= 3; i ++) {
			BreakIterator it = BreakIterator.getWordInstance(GenEx.getCurrentLocale());
			
			it.setText(text);
			int start = it.first();
			int end = it.next();
			int skipped = 0;
			Boolean breakPhrase = false;
			
			while (BreakIterator.DONE != end) {
				ArrayList<String> words = new ArrayList<String>();
				breakPhrase = false;
				skipped = 0;
				
				int j = i;
				for (; j >= 1; j --) {
					words.add(text.substring(start, end));
					
					start = end;
					end = it.next();
					
					if (Character.isSpaceChar(words.get(i - j).charAt(0)) && j == i && skipped == 0) {
						words.remove(i - j);
						
						breakPhrase = true;
						break;
					} else if (Character.isSpaceChar(words.get(i - j).charAt(0))) {
						words.remove(i - j);
						
						skipped ++;
						j ++;
					} else if (! Character.isLetterOrDigit(words.get(i - j).charAt(0))) {
						words.remove(i - j);
						
						breakPhrase = true;
						break;
					} else if (words.get(i - j).length() < 3) {
						words.remove(i - j);
						
						breakPhrase = true;
						break;
					} else if (stopWords.contains(words.get(i - j))) {
						words.remove(i - j);
						
						breakPhrase = true;
						break;
					}
				}
				
				for (; j <= i; j ++) {
					start = it.previous();
					
					if (skipped -- > 1) {
						j --;
						start = it.previous();
					}
				}
				end = it.next();
				
				if (! breakPhrase) {
					StringBuffer sb = new StringBuffer();
					Iterator<String> si = words.iterator();
					
					while (si.hasNext()) {
						String w = si.next();
						
						sb.append(w.substring(0, w.length() > maxLength ? maxLength : w.length()));
						sb.append(" ");
					}
					
					stemPhrases.add(sb.toString().trim());
				}
				
				start = end;
				end = it.next();
			}
		}
	}
	
	public ArrayList<String> getStems() {
		
		if (null == stems) {
			stem();
		}
		
		return stems;
	}
	
	public ArrayList<String> getStemPhrases(String text) {
		
		if (null == stemPhrases) {
			stemPhrases(text);
		}
		
		return stemPhrases;
	}
	
}
